home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-09-04 | 94.4 KB | 1,717 lines |
-
-
-
- - 1 -
-
-
-
- 9. _A_u_d_i_o__F_i_l_e__L_i_b_r_a_r_y
-
- This chapter lists information about the Audio File Library
- programming interface included in the the IRIS Digital Media
- Development Environment. It includes changes, additions,
- and bug fixes since the last release, and known problems,
- workarounds, and caveats.
-
- The Audio File Library consists of approximately 100 C
- routines that allow application programs to read/write audio
- sample data and auxiliary header information to/from a
- number of standard audio file formats. The library requires
- no special audio hardware at runtime, and is useful for
- sound file import/export/conversion operations as well as
- real-time recording/playback.
-
- The Audio File Library API allows you to access audio
- samples and nonaudio information from audio files using a
- common set of routines. The API includes functions for
- reading/writing various types of data including author,
- copyright, name, and annotation strings; sample frame marker
- locations; sample configuration parameters and loop points;
- MIDI exclusive data; and application-defined data.
-
- The Audio File Library implements transparent sample data
- format conversion and compression/decompression for many
- different audio file formats. The following compression
- algorithms are currently supported:
-
- +o MPEG-1 Layers I and II
-
- +o Aware Inc.'s, proprietary MultiRate algorithm
-
- +o CCITT G.711 mu-law and A-law
-
- +o CCITT G.722 ADPCM
-
- +o CCITT G.726 ADPCM
-
- +o CCITT G.728 ADPCM
-
- +o GSM 06.10
-
- +o IMA DVI ADPCM
-
- Transparent format conversion and compression/decompression
- means that application programs can process all audio files
- as uncompressed data in any format that the application
- desires. There is no need to write special code for
- handling different sample formats or types of compressed
- data. Compressed and decompressed files look the same to
-
-
-
-
-
-
-
-
-
-
-
- - 2 -
-
-
-
- applications as long as the compression format is one of the
- supported types listed above.
-
- Note: The Aware MultiRate codec cannot be activated by an
- application without a FlexLM node-locked license,
- available from SGI.
-
- See the online man page _a_w_a_r_e(_5) for an overview of
- the Aware compression technology available to
- developers and end users. The online man page
- _a_f_I_n_i_t_C_o_m_p_r_e_s_s_i_o_n(3dm) describes the Audio File
- Library interface to reading/writing audio files that
- contain MultiRate or other types of compressed data.
-
- The Audio File Library API is intended to be general enough
- to allow support for additional digital audio file formats
- and compression schemes in the future. Applications that
- are developed on top of the 5.3 library will be able to read
- these additional file and data formats (with at most minor
- code modifications) after simply relinking with a 6.x
- version of the Audio File Library. Existing 5.3 applications
- will require slight modifications in order to write
- additional file and data formats.
-
- Applications linked with the 6.x Audio File Library no
- longer need to be linked with any other library. All that
- is needed on the link line is:
-
- ----llllaaaauuuuddddiiiiooooffffiiiilllleeee
-
- The only exception to this is cases where the general
- Digital Media Library error retrieval routine
- _d_m_G_e_t_E_r_r_o_r(3dm) is used (see details below).
-
- The _I_R_I_S _D_i_g_i_t_a_l _M_e_d_i_a _P_r_o_g_r_a_m_m_i_n_g _G_u_i_d_e contains an
- introduction to programming with the Audio File Library,
- along with a description of each of its functions. Please
- see section "Documentation Errors" for some important notes.
-
- The on-line man page _a_f_I_n_t_r_o(3dm) provides a brief overview
- of the library and a list of the available procedure calls.
-
- The IRIS Audio Utility Library is a small C language
- procedure call library that contains approximately 10
- auxiliary routines for use with the Audio File Library.
-
- Please see the _I_R_I_S _D_i_g_i_t_a_l _M_e_d_i_a _P_r_o_g_r_a_m_m_i_n_g _G_u_i_d_e for an
- introduction to programming with Audio Utility Library and a
- detailed description of its functions. Also see the Changes
- and Additions section below for more information about this
- library.
-
-
-
-
-
-
-
-
-
-
-
- - 3 -
-
-
-
- Currently, the library consists of the function
- _A_U_c_h_e_c_k_l_i_c_e_n_s_e(3dm), which allows an application to query
- license availability for Aware compressor/decompressor
- software on the current host, and several functions that
- implement a generalized parameter-value list object for use
- with the new Audio File Library routines
- _a_f_I_n_i_t_C_o_m_p_r_e_s_s_i_o_n_P_a_r_a_m_s(3dm) and
- _a_f_G_e_t_C_o_m_p_r_e_s_s_i_o_n_P_a_r_a_m_s(3dm). See the man page _A_U_p_v_n_e_w(3dm)
- for a description of these routines.
-
- See the source code _a_i_f_c_c_o_n_v_e_r_t._c in the directory
- /_u_s_r/_s_h_a_r_e/_s_r_c/_d_m_e_d_i_a/_s_o_u_n_d_c_o_m_m_a_n_d_s for Audio Utility
- programming example.
-
-
- 9.1 _E_x_a_m_p_l_e__P_r_o_g_r_a_m_s__i_n__/_u_s_r_/_s_h_a_r_e_/_s_r_c_/_d_m_e_d_i_a_/_a_u_d_i_o
-
- The subsystems _d_m_e_d_i_a__d_e_v._s_r_c._t_o_o_l_s and
- _d_m_e_d_i_a__d_e_v._s_r_c._e_x_a_m_p_l_e_s contain several source code examples
- for programming with the Audio File Library. Executable
- versions of some of these programs are included as standard
- system utilities which can be installed from the
- _d_m_e_d_i_a__e_o_e._s_w._t_o_o_l_s subsystem included with the IRIX 6.2 O/S
- release. However, as noted in the Changes section below,
- most of these programs are now obsolete and are only
- provided as example code, and their functionality has been
- taken over by other programs.
-
- _p_l_a_y_a_i_f_c(1) and _r_e_c_o_r_d_a_i_f_c(1) are command-line programs for
- playing and recording AIFF-C/AIFF files, respectively. The
- programs are built on top of the IRIS Audio Library and the
- Audio File Library. The source code for these programs is
- available in
- /_u_s_r/_s_h_a_r_e/_s_r_c/_d_m_e_d_i_a/_s_o_u_n_d_c_o_m_m_a_n_d_s/{_p_l_a_y._c,_s_f_r_e_c_o_r_d._c}
-
- _a_i_f_c_i_n_f_o(1) is a command-line program that parses an AIFF-
- C/AIFF input file and prints a description of the data in
- the file, including characteristics of the audio sample
- data, and a summary of the nonaudio data (strings, loop
- points, and so on) found in the various file header fields.
- The source code is installed in
- /_u_s_r/_s_h_a_r_e/_s_r_c/_d_m_e_d_i_a/_s_o_u_n_d_c_o_m_m_a_n_d_s/_a_i_f_c_i_n_f_o._c.
-
- _a_i_f_f_2_a_i_f_c(1), _a_i_f_c_2_a_i_f_f(1), _a_i_f_c_c_o_m_p_r_e_s_s(1), and
- _a_i_f_c_d_e_c_o_m_p_r_e_s_s(1) are old command-line utility programs for
- converting between AIFF-C and AIFF files, or for converting
- AIFF-C files between compressed and uncompressed data
- formats. These utilities are all obsolete, as indicated
- below. The source for the program is the file
- /_u_s_r/_s_h_a_r_e/_s_r_c/_d_m_e_d_i_a/_s_o_u_n_d_c_o_m_m_a_n_d_s/_a_i_f_c_c_o_n_v_e_r_t._c.
-
-
-
-
-
-
-
-
-
-
-
-
- - 4 -
-
-
-
- 9.2 _C_h_a_n_g_e_s__a_n_d__A_d_d_i_t_i_o_n_s__S_i_n_c_e__6_._2
-
- This section lists changes/additions to the Audio File and
- Audio Utility Library and accompanying example source code
- since its last release.
-
- +o The AF Library now reads and writes Audio Visual
- Research (avr), Amiga IFF/8SVX (iff), SampleVision
- (smp), SoundFont2 (sf2), and VOC file formats in
- addition to the existing set of formats. Information
- about these can be found in the following man pages:
- _a_v_r(4), _i_f_f(4), _s_m_p(4), _s_f_2(4), and _v_o_c(4).
-
- +o Support for parsing of instruments, instrument
- parameters, loops, and markers has been added for all
- file formats which support some form of this
- information.
-
- +o New routines for accessing loop counts and marker
- comments are available.
-
- +o Four new compression types have been added: CCITT
- G.726, CCITT G.728, GSM 06.10, and IMA DVI ADPCM.
-
- +o The Audio File Library now has a _D_M_p_a_r_a_m_s-based
- interface for audio data format parameters as well as
- the old routines.
-
- +o As a result of the previous addition, it is now
- possible to specify details of the format and/or rate
- conversion process via _D_M_p_a_r_a_m_s. This includes such
- things as rate conversion and dithering algorithms.
-
- +o Error reporting within the AF is now handled by a
- thread-safe error reporting routine at all times (even
- when the AFerrorhandler has been disabled).
- Applications that wish to take advantage of this
- feature should call _d_m_G_e_t_E_r_r_o_r(3dm) in cases where an
- AF routine returns an error status.
-
- +o The Audio Utility Library's functionality has been
- included within the Digital Media Library,
- libdmedia.so. For backwards compatibility, a library
- stub still exists for libaudioutil, but new
- applications should use -_l_d_m_e_d_i_a rather than
- -_l_a_u_d_i_o_u_t_i_l.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 5 -
-
-
-
- 9.3 _C_h_a_n_g_e_s__a_n_d__A_d_d_i_t_i_o_n_s__S_i_n_c_e__b_e_t_w_e_e_n__5_._3__a_n_d__6_._2
-
- This section lists changes/additions to the Audio File
- Library and accompanying example source code between the old
- 5.3 version and the newer 6.2 version. This information
- remains available for developers who are upgrading directly
- from a 5.x release to 6.4.
-
- +o The 6.2 AF allows transparent conversion of the audio
- data in a file's track into an uncompressed format of
- the application's choice. This new format is known as
- the _v_i_r_t_u_a_l format of the data. The application need
- not concern itself with the data format in the file; it
- can specify the format in which it would like to
- receive the data. This also works in the other
- direction: A buffer of data in any uncompressed format
- may be written out to a file containing data in any
- other format (assuming the audio file type specified
- supports that format). Read the _a_f_I_n_t_r_o(3dm) man page
- for a detailed explanation of this procedure.
-
- +o The following list of audio utility programs has been
- made obsolete by the new _d_m_c_o_n_v_e_r_t(3dm) and/or
- _d_m_i_n_f_o(3dm) utilities:
-
- aaaaiiiiffffffff2222aaaaiiiiffffcccc,,,, aaaaiiiiffffcccc2222aaaaiiiiffffffff,,,, aaaaiiiiffffccccccccoooommmmpppprrrreeeessssssss,,,, aaaaiiiiffffccccddddeeeeccccoooommmmpppprrrreeeessssssss,,,, aaaaiiiiffffcccciiiinnnnffffoooo
-
- For backwards compatibility, these utilities still
- exist as symbolic links to the new programs. SGI
- offers no guarantee that this will be continued in
- future releases.
-
- +o The 6.x AF has adopted a new standard for the naming of
- publically available routines. All Audio File Library
- routines now consist of the prefix "af" (in small case
- letters) followed by any number of words describing the
- function, with the first letter of each word
- capitalized. To allow existing code to run when linked
- against the new library, two forms of backwards-
- compatibility are built into the library:
-
- +o The public header file <dmedia/audiofile.h>
- contains a set of #define's which will cause the
- preprocessor to rename each occurrence of the old
- routine names in existing code when and if it is
- recompiled from source.
-
- +o For code which is not recompiled but which chooses
- to link against the 2.0 version of the library
- (see the section "How Does This DSO Magic Work?"
- below), a set of wrapper functions are contained
-
-
-
-
-
-
-
-
-
-
-
- - 6 -
-
-
-
- within the library to allow the old routine symbol
- names to be resolved properly. For ease in
- debugging and maximum efficiency, it is
- recommended that programs be recompiled to allow
- the redefines to happen, or better yet, rename the
- function calls using the new scheme.
-
- 9.4 _B_u_g__F_i_x_e_s
-
- This section describes fixes made to the code since the 6.2
- release.
-
- +o Audio format is now properly reset by _a_f_O_p_e_n_F_i_l_e in
- cases where an illegal format was specified for
- creation (ex., unsigned samples for AIFF file).
-
- +o Using an unmodified AFfilesetup to create an audio file
- of any type now creates a file with default values
- without generating any spurious warnings about
- incorrect sample format, etc.
-
- 9.5 _K_n_o_w_n__P_r_o_b_l_e_m_s__a_n_d__W_o_r_k_a_r_o_u_n_d_s
-
- This section lists problems in the new Audio File Library
- software and ways to work around them.
-
- +o AIFF-C comment chunks: the Audio File Library API does
- not yet include routines for reading/writing comment
- chunk data in AIFF-C files. The library routine
- _a_f_O_p_e_n_F_i_l_e(3dm) allows you to open an AIFF-C file that
- contains a comment chunk, but there is no way to access
- the comment chunk fields through library routines.
-
- +o Apple Computer proprietary compression algorithms:
- several compression algorithms described in the AIFF-C
- specification (ACE2, ACE8, MAC3, MAC6) are Apple
- proprietary and cannot be decoded on IRIS workstations.
- To avoid problems with proprietary or unsupported
- compression algorithms, convert AIFF-C files so that
- they contain uncompressed data before attempting to
- transfer them between an IRIS workstation and another
- audio workstation platform.
-
- +o Aware MultiRate codec: An application is only allowed
- to have one AFfilehandle open at a time which uses the
- Aware MultiRate or Lossless compressor or decompressor.
- This applies to the application's entire process share
- group. In addition, the MultiRate algorithm has a
- large number of memory leaks. Avoid opening large
- numbers of MultiRate-compressed files in any single
- application. Due to the limited support which SGI
-
-
-
-
-
-
-
-
-
-
-
- - 7 -
-
-
-
- supplies for this codec, it is unlikely that this will
- be fixed in the foreseeable future.
-
- Note: These bugs does not apply to the SGI MPEG1
- implementation.
-
- 9.6 _D_o_c_u_m_e_n_t_a_t_i_o_n__E_r_r_o_r_s
-
- This section lists errors in the Audio File Library
- documentation.
-
- +o No known errors at this time.
-
-
- 9.7 _A_u_d_i_o__F_i_l_e__L_i_b_r_a_r_y_:__D_e_v_e_l_o_p_e_r__N_o_t_e_s
-
- An important warning to developers about using the IRIX 6.2,
- 6.3 or 6.4 Audio File Library. Read this in order to assure
- that your applications continue to work well with the new
- expanded version of the library.
-
- 9.7.1 _I_n_t_r_o_d_u_c_t_i_o_n It has come to our attention that some
- applications which use the Audio File Library are making
- untrue assumptions about the library. These assumptions,
- though in conflict with the practice laid out by our
- documentation, happened coincidentally not to cause any
- errors with versions of the library shipped with IRIX 5.3
- and earlier. But it is entirely possible that some of these
- mis-coded applications will fail when run with this new
- release of the library.
-
- As the Audio File Library is a Dynamic Shared Object (DSO),
- this is a matter of some concern to developers, as end-users
- may upgrade OS releases and get a new DSO which breaks their
- applications without the applications' developer having had
- a chance to re-release.
-
- The library released with IRIX 6.2 was a superset of the
- previously-released library. New functionality has been
- added and will continue to be added, but all previously-
- existing functions are still present.
-
- This section is provided to warn developers of problems
- which may be experienced with the new releases due to
- incorrect assumptions made in application code.
-
- The first problem involves assumptions about the kinds of
- files the library will be able to open. The second and
- third problems have to do with using the Audio Library in
- multi-threaded applications. The fourth problem involves
- the use of an AFfilehandle's file descriptor while the
-
-
-
-
-
-
-
-
-
-
-
- - 8 -
-
-
-
- filehandle is alive. Then we follow with a warning about
- the correlation between AF calls and actual UNIX operations
- on files (such as read(), write(), and lseek() system
- calls).
-
- 9.7.2 _U_s_e__o_f__t_h_e__O_l_d__V_e_r_s_i_o_n__o_f__t_h_e__A_u_d_i_o__F_i_l_e__L_i_b_r_a_r_y
- Because the confusion described above seems to be fairly
- widespread, and because some of this confusion may have
- stemmed from insufficient emphasis of these points in SGI's
- documentation, the new library has been modified via the SGI
- DSO versioning system so that programs built prior to the
- 6.2 release will still bind to a copy of the old library.
- This means that old AF programs will not be able to get the
- feature and performance improvements of the new Audio File
- Library without relinking. But this will also decrease the
- chances that bugs in developers' application code such as
- the ones described below will be exposed, until the
- developer has a chance to repair their application, relink
- to bind to the new DSO, and ship a new version to their
- customers.
-
- We did this version change as a one-time aid for developers.
- We do not intend to create new DSO versions for each new
- audio file library upgrade.
-
- We give no guarantees that the old version of libaudiofile
- will be maintained in the same manner as the new version, or
- in any way whatsoever. But we can guarantee that we will
- not intentionally make changes to it which would cause
- applications with the below pitfalls to fail. Please note
- however that some of the problems below could happen at any
- time, whether libaudiofile changes or not. Some could
- surface to users as a result of a change of any software on
- the system or even a change of system hardware. So just
- because we are keeping this older libaudiofile.so does not
- mean developers have any guarantee whatsoever that their
- programs will continue to execute fine. All developers
- should check their software for these problems and remove
- them as soon as possible.
-
- 9.7.3 _H_o_w__D_o_e_s__T_h_i_s__D_S_O__M_a_g_i_c__W_o_r_k_? The version of the
- Audio File library which has been shipping since IRIX 5.1 is
- stamped with the interface version "sgi1.0". This can be
- seen by looking at the MIPS_IVERSION entry of the DSO using
- "elfdump -L <library>". Similarly, the new version of the
- Audio File Library is stamped "sgi2.0". When a program
- (specifically, a NON-ABI executable) is linked under IRIX
- 5.x and the DSO is specified on the command line using an
- argument such as -laudiofile, ld looks at the currently
- available DSOs, picks the one called libaudiofile.so, and
- places that DSO's name and its interface version stamp in
-
-
-
-
-
-
-
-
-
-
-
- - 9 -
-
-
-
- the executable's liblist, which can be seen with "elfdump
- -Dl <executable>".
-
- Then at some later time, the executable is run. This could
- be before or after a new version of the Audio File Library
- is installed. The system (specifically, rld) must then find
- a libaudiofile DSO to use which has a major version of 1
- (the major version is the number before the decimal point in
- the interface version stamp "sgi1.0"). If no new version of
- the Audio File Library has been installed, the system will
- immediately find libaudiofile.so, discover that it has an
- interface version of "sgi1.0", and use it. If a new version
- of the Audio File Library has been installed as
- libaudiofile.so, the system will find this DSO first, it
- will look and see that the version number is "sgi2.0", and
- it will reject this file. It will then look for another DSO
- called libaudiofile.so.1, since it wants to find major
- version 1 of this DSO. Since we have now installed the old
- DSO libaudiofile.so.1, the system will find this DSO and use
- it.
-
- In order for an old program to bind to the new DSO, the
- programmer must relink it on a system which has version 2 of
- the DSO. This way, "sgi2.0" will be stored in the entry of
- program's liblist for libaudiofile.so. An alternate way to
- make an AF program bind to the new DSO instead of the old
- (1.0) DSO is to set the environment variable _RLD_ARGS to
- '-ignore_version libaudiofile.so', but this will affect all
- AF programs executed with this environment variable set.
-
- DSOs and DSO versioning are covered in dso(5), ld(1),
- rld(1), and other man pages. dso(5) contains references for
- more information.
-
- 9.7.4 _P_R_O_B_L_E_M__1 Assumption that AF only reads and writes a
- certain set of file and data formats.
-
- The AF is a library which now supports many file formats
- (besides AIFF and AIFF-C) and data formats (besides 2's
- complement integer and compressed data formats).
-
- This is why we always stated in the old man pages that
- certain formats were the "currently supported" formats (man
- afIntro(3dm)), or that certain data formats or chunk
- configurations were possible "from AIFF files" rather than
- "from files".
-
- The Audio File Library has the following behaviors which may
- break applications making the above assumption when a new
- library is released:
-
-
-
-
-
-
-
-
-
-
-
-
- - 10 -
-
-
-
- int filefmt = afIdentifyFD(fd);
- int filefmt = afGetFileFormat(handle, &version);
-
- Applications use afIdentifyFD for two reasons: seeing
- whether the AF recognizes an audio file, and seeing
- specifically which format the audio file has. The user uses
- afGetFileFormat for the latter purpose (as well as getting
- the format version, if applicable). This section covers the
- pitfalls of each use separately:
-
- CHECK FOR RECOGNITION:
-
- The filefmt returned could very well be something other than
- AF_FILE_AIFF or AF_FILE_AIFFC. This version of the library,
- for example, supports six formats. The application should
- make no assumptions about what tokens could be returned.
-
- Therefore code such as:
-
-
- iiiiffff ((((ffffiiiilllleeeeffffmmmmtttt !!!!==== AAAAFFFF____FFFFIIIILLLLEEEE____AAAAIIIIFFFFFFFF &&&&&&&&
- ffffiiiilllleeeeffffmmmmtttt !!!!==== AAAAFFFF____FFFFIIIILLLLEEEE____AAAAIIIIFFFFFFFFCCCC))))
- {{{{
- pppprrrriiiinnnnttttffff((((""""tttthhhhiiiissss ffffiiiilllleeee iiiissss nnnnooootttt ssssuuuuppppppppoooorrrrtttteeeedddd bbbbyyyy tttthhhheeee AAAAFFFF lllliiiibbbbrrrraaaarrrryyyy!!!!\\\\nnnn""""))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- }}}}
-
- is incorrect because it is quite reasonable for the AF to
- return a value other than one found in the include file.
- Instead, the code should test whether the AF did not
- recognize the file format rather than testing for what it
- thinks is all possible recognized formats. Here's one
- example:
-
-
- iiiiffff ((((ffffiiiilllleeeeffffmmmmtttt ======== AAAAFFFF____FFFFIIIILLLLEEEE____UUUUNNNNSSSSUUUUPPPPPPPPOOOORRRRTTTTEEEEDDDD ||||||||
- ffffiiiilllleeeeffffmmmmtttt ======== AAAAFFFF____FFFFIIIILLLLEEEE____UUUUNNNNKKKKNNNNOOOOWWWWNNNN))))
- {{{{
- pppprrrriiiinnnnttttffff((((""""tttthhhhiiiissss ffffiiiilllleeee iiiissss nnnnooootttt ssssuuuuppppppppoooorrrrtttteeeedddd bbbbyyyy tttthhhheeee AAAAFFFF lllliiiibbbbrrrraaaarrrryyyy!!!!\\\\nnnn""""))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- }}}}
-
- The difference here is that the code acknowledges that there
- are file formats which could be returned which the coder did
- not know about at the time of coding.
-
- GETTING THE FORMAT ITSELF
-
- What about programs which actually care what the file format
- of a file they are opening is? Note that this should be
- rare, because in the AF, the data format of a file's track
-
-
-
-
-
-
-
-
-
-
-
- - 11 -
-
-
-
- is queried and manipulated totally independently of the
- file's file format. So only programs which actually have to
- make distinctions like "AIFF vs. AIFF-C" need use
- afGetFileFormat or afIdentifyFD for this purpose.
-
- The caveat here, just as stated above, is that the library
- could easily return something other than one of the
- AF_FILE_... tokens found in /usr/include/audiofile.h at the
- time of compilation. This is because the Audio File Library
- is a dynamic shared object (DSO), and thus when newer
- versions of the audio file library supporting new file
- formats are released with new OS's, programs linked at an
- earlier time will automatically pick up the new library, and
- thus could see the tokens corresponding to the newly
- supported formats.
-
- Before you start worrying about how to handle this
- situation, make sure you have to worry about the file format
- at all:
-
- Many applications which check the filefmt should really be
- checking the sampfmt and other track parameters of the
- file's track. For example, there is no reason why a program
- which simply reads the audio data out of a 16-bit
- AF_SAMPFMT_TWOSCOMP AIFF file would not be able to function
- just as well reading that kind of data out of a NeXT/Sun
- file, as long as it did not intend to read AIFF-specific
- chunks out of it as well (certain miscs and insts, for
- example). Such a program has no need to call afIdentifyFD
- or afGetFileFormat to get the file format.
-
- But for those applications that do care about the file
- format, code such as this:
-
-
- sssswwwwiiiittttcccchhhh ((((aaaaffffIIIIddddeeeennnnttttiiiiffffyyyyFFFFDDDD((((ffffdddd))))))))
- {{{{
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____AAAAIIIIFFFFFFFF::::
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss iiiissss aaaannnn AAAAIIIIFFFFFFFF ffffiiiilllleeee....\\\\nnnn""""))));;;;
- ddddoooo____aaaaiiiiffffffff____tttthhhhiiiinnnngggg(((())));;;;
- bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____AAAAIIIIFFFFFFFFCCCC::::
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss iiiissss aaaannnn AAAAIIIIFFFFFFFF----CCCC ffffiiiilllleeee....\\\\nnnn""""))));;;;
- ddddoooo____aaaaiiiiffffffffcccc____tttthhhhiiiinnnngggg(((())));;;;
- bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____UUUUNNNNKKKKNNNNOOOOWWWWNNNN::::
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____UUUUNNNNSSSSUUUUPPPPPPPPOOOORRRRTTTTEEEEDDDD::::
- pppprrrriiiinnnnttttffff((((""""tttthhhhiiiissss ffffiiiilllleeee iiiissss nnnnooootttt ssssuuuuppppppppoooorrrrtttteeeedddd bbbbyyyy AAAAFFFF lllliiiibbbbrrrraaaarrrryyyy!!!!!!!!\\\\nnnn""""))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- ddddeeeeffffaaaauuuulllltttt::::
- ////**** aaaassssssssuuuummmmeeee tttthhhheeeerrrreeee hhhhaaaassss bbbbeeeeeeeennnn ssssoooommmmeeee pppprrrrooooggggrrrraaaammmmmmmmaaaattttiiiicccc eeeerrrrrrrroooorrrr ****////
-
-
-
-
-
-
-
-
-
-
-
- - 12 -
-
-
-
- pppprrrriiiinnnnttttffff((((""""bbbbaaaadddd rrrreeeettttuuuurrrrnnnn vvvvaaaalllluuuueeee ffffrrrroooommmm AAAAFFFF lllliiiibbbbrrrraaaarrrryyyy!!!!!!!!\\\\nnnn""""))));;;;
- aaaasssssssseeeerrrrtttt((((0000))));;;;
- }}}}
-
- should be changed to code that at least does this:
-
-
- sssswwwwiiiittttcccchhhh ((((aaaaffffIIIIddddeeeennnnttttiiiiffffyyyyFFFFDDDD((((ffffdddd))))))))
- {{{{
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____AAAAIIIIFFFFFFFF::::
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss iiiissss aaaannnn AAAAIIIIFFFFFFFF ffffiiiilllleeee....\\\\nnnn""""))));;;;
- ddddoooo____aaaaiiiiffffffff____tttthhhhiiiinnnngggg(((())));;;;
- bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____AAAAIIIIFFFFFFFFCCCC::::
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss iiiissss aaaannnn AAAAIIIIFFFFFFFF----CCCC ffffiiiilllleeee....\\\\nnnn""""))));;;;
- ddddoooo____aaaaiiiiffffffffcccc____tttthhhhiiiinnnngggg(((())));;;;
- bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____UUUUNNNNKKKKNNNNOOOOWWWWNNNN::::
- ccccaaaasssseeee AAAAFFFF____FFFFIIIILLLLEEEE____UUUUNNNNSSSSUUUUPPPPPPPPOOOORRRRTTTTEEEEDDDD::::
- pppprrrriiiinnnnttttffff((((""""tttthhhhiiiissss ffffiiiilllleeee iiiissss nnnnooootttt ssssuuuuppppppppoooorrrrtttteeeedddd bbbbyyyy AAAAFFFF lllliiiibbbbrrrraaaarrrryyyy!!!!!!!!\\\\nnnn""""))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- ddddeeeeffffaaaauuuulllltttt::::
- pppprrrriiiinnnnttttffff((((""""tttthhhhiiiissss pppprrrrooooggggrrrraaaammmm ccccaaaannnnnnnnooootttt hhhhaaaannnnddddlllleeee tttthhhhiiiissss ffffiiiilllleeee ffffoooorrrrmmmmaaaatttt!!!!\\\\nnnn""""))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- }}}}
-
- Applications can now query the AF at runtime in order to
- determine which file formats are supported by the version of
- the AF to which the running program has bound. In addition
- to querying the token that is used to refer to each file
- format, users can query for the textual name and other
- characteristics of each format. See the _a_f_Q_u_e_r_y(3dm) man
- page for a complete description of this technique.
-
- For many applications, getting the textual name of the file
- format is the entire reason they wanted to call afIdentifyFD
- or afGetFileFormat in the first place, and so such
- applications can be now written so that they instantly and
- automatically understand every file format which the
- currently-bound Audio File Library understands, as in:
-
-
- iiiinnnntttt ffffiiiilllleeeeffffmmmmtttt ==== aaaaffffIIIIddddeeeennnnttttiiiiffffyyyyFFFFDDDD((((ffffdddd))));;;;
- cccchhhhaaaarrrr ****nnnnaaaammmmeeee ==== ((((cccchhhhaaaarrrr ****)))) aaaaffffQQQQuuuueeeerrrryyyyPPPPooooiiiinnnntttteeeerrrr((((AAAAFFFF____QQQQUUUUEEEERRRRYYYYTTTTYYYYPPPPEEEE____FFFFIIIILLLLEEEEFFFFMMMMTTTT,,,,
- AAAAFFFF____QQQQUUUUEEEERRRRYYYY____NNNNAAAAMMMMEEEE,,,, ffffiiiilllleeeeffffmmmmtttt,,,, 0000,,,, 0000))));;;;
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss iiiissss ffffiiiilllleeee hhhhaaaassss tttthhhheeee %%%%ssss ffffiiiilllleeee ffffoooorrrrmmmmaaaatttt....\\\\nnnn"""",,,, nnnnaaaammmmeeee))));;;;
-
- So what guarantees does the developer have?
-
- The library will never support fewer formats. If a user
- uses an AF_FILE_ token that we ship with a software release,
-
-
-
-
-
-
-
-
-
-
-
- - 13 -
-
-
-
- that token and its associated file format will never become
- unsupported, although it may become obsolete (and perhaps
- new features will not be available for it). So for example,
- the library will never stop supporting AF_FILE_AIFF or
- AF_FILE_AIFFC.
-
- The library will always provide the query mechanism. We
- have made every effort to make the query mechanism versatile
- enough that user programs can make intelligent decisions
- about how to deal with and report info on audio files of
- different file formats.
-
- afGetSampleFormat(AFfilehandle, int track, int *sampfmt, int
- *sampwidth);
-
- Here is the single most likely offender that could be found
- in developer's programs. Because the new AF supports
- transparent data format conversion, you may not have to use
- this routine at all, and many of the below-mentioned issues
- will go away.
-
- As the man page says, AIFF and AIFF-C files only support
- AF_SAMPFMT_TWOSCOMP files. However, as the library now
- support other file formats, it is quite likely the library
- may return some other sample format. So code that says:
-
-
- AAAAFFFFffffiiiilllleeeehhhhaaaannnnddddlllleeee hhhh ==== aaaaffffOOOOppppeeeennnnFFFFiiiilllleeee((((................))));;;;
- iiiiffff ((((!!!!hhhh)))) rrrreeeettttuuuurrrrnnnn;;;;
-
- aaaaffffGGGGeeeettttSSSSaaaammmmpppplllleeeeFFFFoooorrrrmmmmaaaatttt((((hhhh,,,, AAAAFFFF____DDDDEEEEFFFFAAAAUUUULLLLTTTT____TTTTRRRRAAAACCCCKKKK,,,, &&&&ssssaaaammmmppppffffmmmmtttt,,,, &&&&ssssaaaammmmppppwwwwiiiiddddtttthhhh))));;;;
-
- ////**** ssssaaaammmmppppffffmmmmtttt ccccoooouuuulllldddd oooonnnnllllyyyy bbbbeeee AAAAFFFF____SSSSAAAAMMMMPPPPFFFFMMMMTTTT____TTTTWWWWOOOOSSSSCCCCOOOOMMMMPPPP--------nnnnoooo nnnneeeeeeeedddd ttttoooo cccchhhheeeecccckkkk!!!! ****////
-
- sssswwwwiiiittttcccchhhh ((((ssssaaaammmmppppwwwwiiiiddddtttthhhh))))
- {{{{
- ............ ////**** sssseeeeeeee bbbbeeeelllloooowwww ffffoooorrrr nnnnooootttteeee oooonnnn tttthhhhiiiissss ppppaaaarrrrtttt ****////
- }}}}
-
- is incorrect. It is by no means guaranteed that sampfmt is
- two's complement. Nor is it guaranteed that sampwidth has
- any meaning--the meaning of sampwidth depends on sampfmt.
-
- For example, this version of the Audio File Library can
- transfer IEEE floats and IEEE doubles. For these types,
- sampwidth has no meaning, and it is ignored and unset. The
- code above would behave very unpredictably.
-
- Code should say:
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 14 -
-
-
-
- AAAAFFFFffffiiiilllleeeehhhhaaaannnnddddlllleeee hhhh ==== aaaaffffOOOOppppeeeennnnFFFFiiiilllleeee((((................))));;;;
- iiiiffff ((((!!!!hhhh)))) rrrreeeettttuuuurrrrnnnn;;;;
-
- aaaaffffGGGGeeeettttSSSSaaaammmmpppplllleeeeFFFFoooorrrrmmmmaaaatttt((((hhhh,,,, AAAAFFFF____DDDDEEEEFFFFAAAAUUUULLLLTTTT____TTTTRRRRAAAACCCCKKKK,,,, &&&&ssssaaaammmmppppffffmmmmtttt,,,, &&&&ssssaaaammmmppppwwwwiiiiddddtttthhhh))));;;;
-
- iiiiffff ((((ssssaaaammmmppppffffmmmmtttt !!!!==== AAAAFFFF____SSSSAAAAMMMMPPPPFFFFMMMMTTTT____TTTTWWWWOOOOSSSSCCCCOOOOMMMMPPPP))))
- {{{{
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss pppprrrrooooggggrrrraaaammmm ccccaaaannnn''''tttt rrrreeeeaaaadddd aaaauuuuddddiiiioooo ffffiiiilllleeeessss ooooffff tttthhhhiiiissss """"
- ssssaaaammmmpppplllleeee ffffoooorrrrmmmmaaaatttt\\\\nnnn""""))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- }}}}
-
- sssswwwwiiiittttcccchhhh ((((ssssaaaammmmppppwwwwiiiiddddtttthhhh)))) ////**** nnnnoooowwww wwwweeee kkkknnnnoooowwww ssssaaaammmmppppwwwwiiiiddddtttthhhh iiiissss mmmmeeeeaaaannnniiiinnnnggggffffuuuullll ****////
- {{{{
- ............ ////**** sssseeeeeeee bbbbeeeelllloooowwww ffffoooorrrr nnnnooootttteeee oooonnnn tttthhhhiiiissss ppppaaaarrrrtttt ****////
- }}}}
-
- Another note on sampwidth: even with AIFF files, the sample
- width is not necessarily a multiple of 8. Generally, this
- can be ignored, because audio samples which do not take up
- an integral number of bytes are left-justified inside the
- next larger integral number of bytes (with the remaining
- bits set to 0). But this may be an issue in code such as
- the switch statement above, if it were written:
-
-
- sssswwwwiiiittttcccchhhh ((((ssssaaaammmmppppwwwwiiiiddddtttthhhh)))) ////**** nnnnoooowwww ssssaaaammmmppppwwwwiiiiddddtttthhhh iiiissss mmmmeeeeaaaannnniiiinnnnggggffffuuuullll ****////
- {{{{
- ccccaaaasssseeee 8888:::: ddddoooo____8888____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee 11116666:::: ddddoooo____11116666____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee 22224444:::: ddddoooo____22224444____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee 33332222:::: ddddoooo____33332222____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ddddeeeeffffaaaauuuulllltttt::::
- ////**** ffffaaaallllsssseeee aaaassssssssuuuummmmppppttttiiiioooonnnn ****////
- pppprrrriiiinnnnttttffff((((""""bbbbaaaadddd rrrreeeettttuuuurrrrnnnn vvvvaaaalllluuuueeee ffffrrrroooommmm AAAAFFFF lllliiiibbbbrrrraaaarrrryyyy!!!!\\\\nnnn""""))));;;;
- aaaasssssssseeeerrrrtttt((((0000))));;;;
- }}}}
-
- There are two problems here. One is that the code assumes
- the maximum size of samples in files opened by the library
- is 32 bits, which is definitely not true. The second false
- assumption is that the number of bits will be a multiple of
- 8. Better code would be (after checking that sampfmt is an
- integer format):
-
-
- ////**** rrrroooouuuunnnndddd ssssaaaammmmppppwwwwiiiiddddtttthhhh uuuupppp ttttoooo nnnneeeeaaaarrrreeeesssstttt nnnnuuuummmmbbbbeeeerrrr ooooffff bbbbyyyytttteeeessss ****////
- iiiinnnntttt nnnnbbbbyyyytttteeeessss ==== (((( ((((ssssaaaammmmppppwwwwiiiiddddtttthhhh----1111)))) //// 8888 )))) ++++ 1111;;;;
- sssswwwwiiiittttcccchhhh ((((nnnnbbbbyyyytttteeeessss))))
- {{{{
- ccccaaaasssseeee 1111:::: ddddoooo____8888____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
-
-
-
-
-
-
-
-
-
-
-
- - 15 -
-
-
-
- ccccaaaasssseeee 2222:::: ddddoooo____11116666____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee 3333:::: ddddoooo____22224444____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ccccaaaasssseeee 4444:::: ddddoooo____33332222____tttthhhhiiiinnnngggg(((())));;;; bbbbrrrreeeeaaaakkkk;;;;
- ddddeeeeffffaaaauuuulllltttt::::
- pppprrrriiiinnnnttttffff((((""""TTTThhhhiiiissss pppprrrrooooggggrrrraaaammmm ccccaaaannnn''''tttt rrrreeeeaaaadddd aaaauuuuddddiiiioooo ffffiiiilllleeeessss ooooffff tttthhhhiiiissss """"
- ssssaaaammmmpppplllleeee wwwwiiiiddddtttthhhh %%%%dddd\\\\nnnn"""",,,, ssssaaaammmmppppwwwwiiiiddddtttthhhh))));;;;
- eeeexxxxiiiitttt((((0000))));;;;
- }}}}
-
- One final thing about sample widths--don't forget that there
- is a special case for reading 24-bit integer data. Because
- 3-byte data is so difficult to deal with, the library
- automatically stretches the data out into convenient 4-byte
- quantities in a way compatible with the SGI Audio Library
- (AL). The tricky thing here is that the data is sign-
- extended on the left for this special case of 17-24-bit
- data, whereas the padding that goes on to handle non-
- multiple-of-8 sample widths is done by zero-bit-padding on
- the right. Here are some examples which should make this
- clear, for the case of AF_SAMPFMT_TWOSCOMP:
-
-
- MMMMSSSSBBBB LLLLSSSSBBBB
- bbbbyyyytttteeee 3333 bbbbyyyytttteeee 2222 bbbbyyyytttteeee 1111 bbbbyyyytttteeee 0000
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddd |||| SSSSaaaammmmpppplllleeee FFFFoooorrrrmmmmaaaatttt
- ------------------------------------------------------------------------------------------------------------------------------------++++--------------------------------------------------------------------------------------------------------------------------------
- dddddddddddddddddddddddd00000000 |||| 6666----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 8888 bbbbiiiittttssss
- RRRRRRRR |||| ((((rrrriiiigggghhhhtttt ppppaaaadddd))))
- ||||
- dddddddddddddddddddddddddddddddd |||| 8888----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 8888 bbbbiiiittttssss
- |||| ((((nnnnoooo ppppaaaaddddddddiiiinnnngggg))))
- ||||
- ccccccccccccccccccccccccccccccccdddddddddddddddd0000000000000000 |||| 11112222----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 11116666 bbbbiiiittttssss
- RRRRRRRRRRRRRRRR |||| ((((rrrriiiigggghhhhtttt ppppaaaadddd))))
- ||||
- ccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddd |||| 11116666----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 11116666 bbbbiiiittttssss
- |||| ((((nnnnoooo ppppaaaaddddddddiiiinnnngggg))))
- ||||
- ssss<<<<------------------------bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccdddddddddddddddd0000000000000000 |||| 22220000----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 33332222 bbbbiiiittttssss
- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS RRRRRRRRRRRRRRRR |||| ((((lllleeeefffftttt ssssiiiiggggnnnn----eeeexxxxtttteeeennnndddd AAAANNNNDDDD rrrriiiigggghhhhtttt ppppaaaadddd !!!!))))
- ||||
- ssss<<<<------------------------bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddd |||| 22224444----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 33332222 bbbbiiiittttssss
- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS |||| ((((lllleeeefffftttt ssssiiiiggggnnnn----eeeexxxxtttteeeennnndddd))))
- ||||
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccdddddddddddddddddddddddd00000000 |||| 33330000----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 33332222 bbbbiiiittttssss
- RRRRRRRR |||| ((((rrrriiiigggghhhhtttt ppppaaaadddd))))
- ||||
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddd |||| 33332222----bbbbiiiitttt ddddaaaattttaaaa ttttaaaakkkkeeeessss 33332222 bbbbiiiittttssss
- |||| ((((nnnnoooo ppppaaaaddddddddiiiinnnngggg))))
- ||||
-
-
-
-
-
-
-
-
-
-
-
-
- - 16 -
-
-
-
- Unlike file formats, it doesn't make sense to have a runtime
- query of all possible sample formats. The existence of the
- new virtual audio format system described above allows
- applications to specify in which format they wish to receive
- data.
-
- int afGetCompression(AFfilehandle, int);
- void afGetCompressionParams(AFfilehandle, int, int *, AUpvlist);
-
- Obviously, new compression methods will be supported, so the
- same warnings that apply to afGetSampleFormat apply here.
-
- As the library transparently decompresses input data and
- compresses output data, this is not such a big issue. The
- application simply must specify the virtual format desired.
-
- A given already-released codec in our library will not
- change its native sample format, if we have specified what
- that codec's native sample format is. So, for example, if
- you know the file is AF_COMPRESSION_G711_ULAW, then you can
- assume the native format for that codec is
- AF_SAMPFMT_TWOSCOMP, 16 because we said this in a man page.
- This is for backwards compatibility. But we do not guarantee
- that all future codecs will generate 16-bit signed integer
- data natively, nor do we guarantee that all future codecs
- will have a single native sample format (some may be
- configurable or may vary depending on what kind of data was
- originally compressed). In every case though, the
- programmer can call afGetSampleFormat to retrieve the sample
- format for the current codec on the file corresponding to
- the given AFfilehandle.
-
- This new version of the library has a runtime query of all
- of the supported compression methods, their textual names,
- their compression ratios (if available), and any other info
- that may be useful in making a runtime choice of codec.
- This is done via afQuery(3dm) in a similar manner to the
- file format name string query above.
-
- int afGetChannels(AFfilehandle, int/*track*/);
-
- May return any number of channels, just like it could even
- with AIFF and AIFF-C. The virtual number of channels may be
- set to any nonzero value.
-
- double afGetRate(AFfilehandle, int/*track*/);
-
- May return any sampling rate, just like it could even with
- AIFF and AIFF-C. The current version of the library
- provides a transparent conversion mechanism which allows the
- programmer to deal with files with unexpected sampling rates
-
-
-
-
-
-
-
-
-
-
-
- - 17 -
-
-
-
- in a simple and clean way via virtual format conversion.
- See _a_f_S_e_t_V_i_r_t_u_a_l_R_a_t_e(3dm) for more information.
-
- int afGetTrackIDs(AFfilehandle, int */*track ids*/);
-
- May return more than one track. We give no guarantees that
- only one-track formats are supported. An application might
- want to reject such a file, or perhaps use the first track.
- We do not define the correct behavior.
-
- int afGetMarkIDs(AFfilehandle, int/*track*/, int */*ids*/);
- int afGetMarkPosition(AFfilehandle, int/*track*/, int/*markid*/);
- char *afGetMarkName(AFfilehandle, int, int);
-
- May return any configuration or number of marks just as it
- may with an AIFF/AIFF-C file.
-
- Apps should be written to expect and ignore marks they do
- not understand.
-
- int afGetMiscIDs(AFfilehandle, int * /*idlist*/);
- int afGetMiscType(AFfilehandle, int /*miscid*/);
- int afGetMiscSize(AFfilehandle, int /*miscid*/);
-
- May return ANY type of misc chunk.
-
- Apps should be written to expect and ignore miscellaneous
- chunks they do not understand.
-
- Apps should be especially careful not to copy misc chunks
- from one file to another unless they understand the content
- of those misc chunks; the chunk may contain references to
- other parts of the file which the application has modified.
- In this case the chunk in the new file becomes corrupt.
- This is to be avoided. The chunk should not be copied and
- the user should probably be warned.
-
- int afGetAESChannelData(AFfilehandle,int,unsigned char buf[24]);
-
- Will always return data that is to be interpreted as AES
- channel data, but there is never any guarantee that such
- data will be present or not in a given file format (unless
- that file format itself defines AES data as always being
- present).
-
- int afGetInstIDs(AFfilehandle, int */*inst ids*/);
- long afGetInstParamLong(AFfilehandle, int/*inst*/, int /*param*/);
-
- May return more than one inst, unlike the one fixed INST in
- AIFF/AIFF-C files. There are many supported file formats
- which have different inst configurations than AIFF/AIFF-C.
-
-
-
-
-
-
-
-
-
-
-
- - 18 -
-
-
-
- The _a_f_Q_u_e_r_y mechanism allows an application to determine in
- advance the number of inst chunks supported by a particular
- file format. Note that this is the allowable number for
- creating a file, not an indication of how many chunks are
- present in a file being read. _a_f_G_e_t_I_n_s_t_I_D_s _M_U_S_T be used to
- determine the number present in a file opened for read
- access prior to loading the values into an array. This is
- very important. The following code will dump core when
- reading some of the currently supported file formats:
-
-
- AAAAFFFFffffiiiilllleeeehhhhaaaannnnddddlllleeee hhhh ==== aaaaffffOOOOppppeeeennnnFFFFiiiilllleeee((((................))));;;;
- iiiinnnntttt iiiinnnnssssttttIIIIDDDD;;;; ////**** iiiinnnnccccoooorrrrrrrreeeecccctttt aaaassssssssuuuummmmppppttttiiiioooonnnn tttthhhhaaaatttt tttthhhheeeerrrreeee iiiissss oooonnnnllllyyyy oooonnnneeee iiiinnnnsssstttt IIIIDDDD!!!! ****////
- iiiiffff ((((!!!!hhhh)))) rrrreeeettttuuuurrrrnnnn;;;;
- aaaaffffGGGGeeeettttIIIInnnnssssttttIIIIDDDDssss((((hhhh,,,, AAAAFFFF____DDDDEEEEFFFFAAAAUUUULLLLTTTT____TTTTRRRRAAAACCCCKKKK,,,, &&&&iiiinnnnssssttttIIIIDDDD))));;;; ////**** CCCCOOOORRRREEEE DDDDUUUUMMMMPPPP!!!!!!!! ****////
-
- The correct code should say:
-
-
- iiiinnnntttt ****iiiinnnnssssttttIIIIDDDDssss ==== NNNNUUUULLLLLLLL;;;; ////**** ffffoooorrrr aaaarrrrrrrraaaayyyy ttttoooo----bbbbeeee----aaaallllllllooooccccaaaatttteeeedddd ****////
- iiiinnnntttt nnnnuuuummmmIIIIDDDDSSSS;;;;
- AAAAFFFFffffiiiilllleeeehhhhaaaannnnddddlllleeee hhhh ==== aaaaffffOOOOppppeeeennnnFFFFiiiilllleeee((((................))));;;;
- iiiiffff ((((!!!!hhhh)))) rrrreeeettttuuuurrrrnnnn;;;;
-
- nnnnuuuummmmIIIIDDDDssss ==== aaaaffffGGGGeeeettttIIIInnnnssssttttIIIIDDDDssss((((hhhh,,,, AAAAFFFF____DDDDEEEEFFFFAAAAUUUULLLLTTTT____TTTTRRRRAAAACCCCKKKK,,,, NNNNUUUULLLLLLLL))));;;; ////**** cccchhhheeeecccckkkk nnnnuuuummmmbbbbeeeerrrr FFFFIIIIRRRRSSSSTTTT ****////
-
- iiiiffff((((nnnnuuuummmmIIIIDDDDssss >>>> 0000)))) {{{{
- iiiinnnnssssttttIIIIDDDDssss ==== ((((iiiinnnntttt ****)))) mmmmaaaalllllllloooocccc((((nnnnuuuummmmIIIIDDDDssss **** ssssiiiizzzzeeeeooooffff((((iiiinnnntttt))))))));;;; ////**** aaaallllllllooooccccaaaatttteeee aaaarrrrrrrraaaayyyy ****////
- iiiiffff((((!!!!iiiinnnnssssttttIIIIDDDDssss)))) {{{{
- eeeerrrrrrrroooorrrr(((())));;;;
- rrrreeeettttuuuurrrrnnnn;;;;
- }}}}
-
- aaaaffffGGGGeeeettttIIIInnnnssssttttIIIIDDDDssss((((hhhh,,,, AAAAFFFF____DDDDEEEEFFFFAAAAUUUULLLLTTTT____TTTTRRRRAAAACCCCKKKK,,,, iiiinnnnssssttttIIIIDDDDssss))));;;; ////**** nnnnoooowwww llllooooaaaadddd IIIIDDDD aaaarrrrrrrraaaayyyy ****////
-
- ////**** ddddoooo wwwwhhhhaaaatttteeeevvvveeeerrrr wwwwiiiitttthhhh iiiinnnnssssttttIIIIDDDDssss ****////
-
- ffffrrrreeeeeeee((((iiiinnnnssssttttIIIIDDDDssss))));;;; ////**** ffffrrrreeeeeeee tttthhhheeee mmmmeeeemmmmoooorrrryyyy ****////
- }}}}
-
- Apps should be written to expect and ignore instrument
- configurations or instrument parameters they do not
- understand.
-
- int afGetLoopIDs(AFfilehandle, int /*inst*/, int*);
- int afGetLoopMode(AFfilehandle, int/*inst*/, int /*loopid */);
- int afGetLoopStart(AFfilehandle, int/*inst*/, int/*loopid */);
- int afGetLoopEnd(AFfilehandle, int/*inst*/, int/*loopid*/);
- int afGetLoopTrack(AFfilehandle, int/*inst*/, int/*loopid*/);
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 19 -
-
-
-
- May return any configurations of loops within an inst, not
- just the fixed value of 2 we have in AIFF/AIFF-C files.
- There are many supported file formats which have different
- loop configurations than AIFF/AIFF-C.
-
- The _a_f_Q_u_e_r_y mechanism allows an application to determine in
- advance the number of loops per inst supported by a
- particular file format. _a_f_G_e_t_L_o_o_p_I_D_s _M_U_S_T be used to
- determine the number present in a file opened for read
- access prior to loading the values into an array. See the
- above note for afGetInstIDs for details.
-
- Apps should be written to expect and ignore loop
- configurations they do not understand.
-
- 9.7.5 _P_R_O_B_L_E_M__2 Some developers are writing bad multi-
- threaded code that just happens to work with the AF library.
-
- We have caught several different apps trying to do the
- following from multi-threaded code and we imagine that there
- are other apps that do this as well:
-
-
- ================================ TTTThhhhrrrreeeeaaaadddd 1111 ========================================================||||============================================ TTTThhhhrrrreeeeaaaadddd 2222 ============================================
- |||| |||| ||||
- |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee |||| |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee
- |||| nnnnoooo sssseeeemmmmaaaapppphhhhoooorrrreeee lllloooocccckkkkiiiinnnngggg |||| |||| nnnnoooo sssseeeemmmmaaaapppphhhhoooorrrreeee lllloooocccckkkkiiiinnnngggg
- |||| |||| ||||
- ||||
- aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee1111))));;;; |||| aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee2222))));;;;
- aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;; |||| aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;;
- ||||
- |||| |||| ||||
- |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee |||| |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee
- |||| nnnnoooo sssseeeemmmmaaaapppphhhhoooorrrreeee lllloooocccckkkkiiiinnnngggg |||| |||| nnnnoooo sssseeeemmmmaaaapppphhhhoooorrrreeee lllloooocccckkkkiiiinnnngggg
- |||| |||| ||||
-
- Both threads are making calls on the same AFfilehandle at
- the same time, and no concern is put into the order in which
- these calls end up being made on the filehandle.
-
- This code is just plain old flat out wrong, it doesn't
- matter if you're using the AF or any other library.
-
- It is entirely possible that the order the calls get
- executed in by the UNIX scheduler is:
-
-
- aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee1111))));;;; ||||
- |||| aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee2222))));;;;
- aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;; ||||
-
-
-
-
-
-
-
-
-
-
-
- - 20 -
-
-
-
- |||| aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;;
-
- in which case both threads would read the wrong data. UNIX
- offers absolutely, positively no guarantee that this will
- not happen unless the programmer uses one of the many
- available process coordination facilities such as
- semaphores.
-
- Furthermore, no amount of work on the part of the AF library
- writers can prevent this situation, because the library has
- no knowledge of what order the programmer really wants the
- operations to come in. We cannot use the pid as a hint
- because some correctly coded programs may want to seek in
- one thread and read in another (correctly coded programs use
- locking to make sure that these operations happen in the
- right order).
-
- Note that although our example only uses the functions
- afSeekFrame() and afReadFrames(), this problem can exist
- with calls to ANY Audio File Library functions, even ones
- which do not directly manipulate audio files (such as
- operations on an AFfilesetup or operations on an
- AFfilehandle that query or set parameters stored in memory).
- In particular, watch out for uncoordinated calls of
- afSyncFile() and afCloseFile(). Making these calls from
- more than one thread simultaneously in an uncoordinated
- fashion seems to be a common error.
-
- Correct code should look like this:
-
-
- ================================ TTTThhhhrrrreeeeaaaadddd 1111 ========================================================||||============================================ TTTThhhhrrrreeeeaaaadddd 2222 ============================================
- ||||
- |||| |||| ||||
- |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee |||| |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee
- |||| |||| ||||
- |||| |||| ||||
- ||||
- LLLLoooocccckkkk SSSSeeeemmmmaaaapppphhhhoooorrrreeee tttthhhhaaaatttt gggguuuuaaaarrrrddddssss hhhh |||| LLLLoooocccckkkk SSSSeeeemmmmaaaapppphhhhoooorrrreeee tttthhhhaaaatttt gggguuuuaaaarrrrddddssss hhhh
- aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee1111))));;;; |||| aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee2222))));;;;
- aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;; |||| aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;;
- UUUUnnnnlllloooocccckkkk SSSSeeeemmmmaaaapppphhhhoooorrrreeee tttthhhhaaaatttt gggguuuuaaaarrrrddddssss hhhh |||| UUUUnnnnlllloooocccckkkk sssseeeemmmmaaaapppphhhhoooorrrreeee tttthhhhaaaatttt gggguuuuaaaarrrrddddssss hhhh
- ||||
- |||| |||| ||||
- |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee |||| |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee
- |||| |||| ||||
- |||| |||| ||||
- ||||
-
- The key thing to realize here is: UNIX guarantees that only
- one of the Lock Semaphore calls will succeed immediately.
-
-
-
-
-
-
-
-
-
-
-
- - 21 -
-
-
-
- The thread whose lock does not succeed will sit and wait in
- the Lock Semaphore call (and thus not proceed to the
- afSeekFrame) until the other thread has unlocked the
- semaphore (after doing its seek AND its read). Then when
- the other thread unlocks the semaphore, the thread who was
- forced to wait will now proceed.
-
- How does one use these semaphores? One uses code such as
- the following to create a semaphore FileOpSema with value 1:
-
-
- ####iiiinnnncccclllluuuuddddeeee <<<<uuuulllloooocccckkkkssss....hhhh>>>>
-
- AAAAFFFFffffiiiilllleeeehhhhaaaannnnddddlllleeee hhhh;;;; ////**** gggglllloooobbbbaaaallll ffffiiiilllleeee hhhhaaaannnnddddlllleeee ****////
- uuuusssseeeemmmmaaaa____tttt ****FFFFiiiilllleeeeOOOOppppSSSSeeeemmmmaaaa;;;; ////**** gggglllloooobbbbaaaallll sssseeeemmmmaaaapppphhhhoooorrrreeee ttttoooo pppprrrrooootttteeeecccctttt hhhh ****////
-
- ////**** iiiinnnniiiittttiiiiaaaalllliiiizzzzeeee sssseeeemmmmaaaapppphhhhoooorrrreeee ssssuuuuppppppppoooorrrrtttt -------- ddddoooo tttthhhhiiiissss oooonnnncccceeee ****////
- {{{{
- uuuussssppppttttrrrr____tttt ****uuuussssppppttttrrrr;;;;
- cccchhhhaaaarrrr ****aaaarrrreeeennnnaaaaffffiiiilllleeee;;;;
-
- ////**** uuuusssseeee ffffaaaasssstttteeeesssstttt ((((nnnnoooo ddddeeeebbbbuuuuggggggggiiiinnnngggg)))) ffffoooorrrrmmmm ooooffff sssseeeemmmmaaaapppphhhhoooorrrreeeessss -------- uuuussssccccoooonnnnffffiiiigggg ((((3333PPPP)))) ****////
- uuuussssccccoooonnnnffffiiiigggg((((CCCCOOOONNNNFFFF____LLLLOOOOCCCCKKKKTTTTYYYYPPPPEEEE,,,, UUUUSSSS____NNNNOOOODDDDEEEEBBBBUUUUGGGG))));;;;
-
- ////**** ccccrrrreeeeaaaatttteeee sssshhhhaaaarrrreeeedddd aaaarrrreeeennnnaaaa ttttoooo hhhhoooolllldddd tttthhhheeee sssseeeemmmmaaaapppphhhhoooorrrreeee -------- uuuussssiiiinnnniiiitttt((((3333PPPP)))) ****////
- aaaarrrreeeennnnaaaaffffiiiilllleeee ==== ttttmmmmppppnnnnaaaammmm((((NNNNUUUULLLLLLLL))));;;;
- uuuussssppppttttrrrr ==== uuuussssiiiinnnniiiitttt((((aaaarrrreeeennnnaaaaffffiiiilllleeee))));;;;
-
- ////****
- ccccrrrreeeeaaaatttteeee tttthhhheeee sssseeeemmmmaaaapppphhhhoooorrrreeee iiiinnnn tttthhhhaaaatttt aaaarrrreeeennnnaaaa -------- uuuussssnnnneeeewwwwsssseeeemmmmaaaa((((3333PPPP))))
- ccccrrrreeeeaaaatttteeee wwwwiiiitttthhhh ccccoooouuuunnnntttt 1111--------tttthhhheeeerrrreeee iiiissss 1111 rrrreeeessssoooouuuurrrrcccceeee ((((hhhh)))),,,, wwwwhhhhiiiicccchhhh iiiissss
- iiiinnnniiiittttiiiiaaaallllllllyyyy aaaavvvvaaaaiiiillllaaaabbbblllleeee....
- ****////
- FFFFiiiilllleeeeOOOOppppSSSSeeeemmmmaaaa ==== uuuussssnnnneeeewwwwsssseeeemmmmaaaa((((uuuussssppppttttrrrr,,,,1111))));;;;
-
- ////**** wwwweeee wwwwoooonnnn''''tttt nnnneeeeeeeedddd ttttoooo rrrreeeeffffeeeerrrr ttttoooo aaaarrrreeeennnnaaaa aaaaggggaaaaiiiinnnn ssssoooo wwwweeee ccccaaaannnn uuuunnnnlllliiiinnnnkkkk ffffiiiilllleeee ****////
- uuuunnnnlllliiiinnnnkkkk((((aaaarrrreeeennnnaaaaffffiiiilllleeee))));;;;
- }}}}
-
- Then one uses uspsema(3P) to lock the semaphore, and
- usvsema(3P) to unlock the semaphore. Pretty simple:
-
-
- ================================ TTTThhhhrrrreeeeaaaadddd 1111 ========================================================||||============================================ TTTThhhhrrrreeeeaaaadddd 2222 ============================================
- ||||
- |||| |||| ||||
- |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee |||| |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee
- |||| |||| ||||
- |||| |||| ||||
- ||||
- uuuussssppppsssseeeemmmmaaaa((((FFFFiiiilllleeeeOOOOppppSSSSeeeemmmmaaaa))));;;; ////****lllloooocccckkkk****//// |||| uuuussssppppsssseeeemmmmaaaa((((FFFFiiiilllleeeeOOOOppppSSSSeeeemmmmaaaa))));;;; ////****lllloooocccckkkk****////
-
-
-
-
-
-
-
-
-
-
-
- - 22 -
-
-
-
- aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee1111))));;;; |||| aaaaffffSSSSeeeeeeeekkkkFFFFrrrraaaammmmeeee((((hhhh,,,,ttttrrrraaaacccckkkk,,,,ppppllllaaaacccceeee2222))));;;;
- aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;; |||| aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,,ttttrrrraaaacccckkkk,,,,............))));;;;
- uuuussssvvvvsssseeeemmmmaaaa((((FFFFiiiilllleeeeOOOOppppSSSSeeeemmmmaaaa))));;;; ////****uuuunnnnlllloooocccckkkk****//// |||| uuuussssvvvvsssseeeemmmmaaaa((((FFFFiiiilllleeeeOOOOppppSSSSeeeemmmmaaaa))));;;; ////****uuuunnnnlllloooocccckkkk****////
- ||||
- |||| |||| ||||
- |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee |||| |||| ssssoooommmmeeee aaaammmmoooouuuunnnntttt ooooffff ttttiiiimmmmeeee
- |||| |||| ||||
- |||| |||| ||||
- ||||
-
- Now, why are we pointing this out for AF users?
-
- We have found several applications which were actually
- committing this error and were GETTING AWAY WITH IT! By the
- most arcane of coincidences of CPU scheduler timings, these
- apps just happened to never fall into the short window of
- time in which the above worst-case scenario could occur.
-
- When these programs were recompiled with an alpha version of
- a newer Audio File Library, which contains different code
- and thus has slightly different timing characteristics and
- gets scheduled slightly differently, the bug in these
- applications was instantly revealed.
-
- This is why we want to alert developers to check their code
- for this-- there could be a bug of this type in their code
- which had previously not come out, just because the old AF
- happens to have had this property (by no design of our own).
- We want to give developers plenty of advanced warning about
- this situation.
-
- 9.7.6 _P_R_O_B_L_E_M__3 Some developers are writing multi-threaded
- code that would be good under their assumption that the AF
- is MT/MP-safe. But this assumption is false.
-
- The AF is NOT a multi-thread and/or multi-processor safe
- library, in the following sense:
-
- Users can make multiple, simultaneous, uncoordinated AF
- calls on different AFfilehandles from different threads and
- the library will operate fine. Each AFfilehandle completely
- encapsulates the state needed to do operations on that
- AFfilehandle (except for error handling, which is explained
- next).
-
- Users cannot make multiple, simultaneous, uncoordinated AF
- calls from different threads to set or access the library's
- global state--namely, the error handler function. If two
- threads simultaneously try and set the error handler (even
- the same error handler), the behavior is undefined.
- Furthermore, if the user writes an error handler, then makes
-
-
-
-
-
-
-
-
-
-
-
- - 23 -
-
-
-
- multiple, simultaneous, uncoordinated AF calls on different
- filehandles from different threads, and both AF calls issue
- an error simultaneously, then two instances of the user's
- error handler will be called in a simultaneous,
- uncoordinated manner in two threads. If this situation is
- possible in a user's program, the user should use semaphores
- in their error handler in order to make sure their handler
- doesn't try and report or deal with two errors at the same
- time. Note that any AF function can cause an AF error to
- occur. Do not assume a function will not err just because
- it is simple.
-
- A thread-safe error handling routine is now available via
- the Digital Media Library. Any application which is
- expected to function in a multi-threaded fashion should
- disable the old global _A_F_e_r_r_o_r_h_a_n_d_l_e_r and use
- _d_m_G_e_t_E_r_r_o_r(3dm) in its place. Here is a simple example:
-
-
- ####iiiinnnncccclllluuuuddddeeee <<<<ssssttttddddiiiioooo....hhhh>>>>
- ####iiiinnnncccclllluuuuddddeeee <<<<ddddmmmmeeeeddddiiiiaaaa////ddddmmmmeeeeddddiiiiaaaa....hhhh>>>>
- ####iiiinnnncccclllluuuuddddeeee <<<<ddddmmmmeeeeddddiiiiaaaa////aaaauuuuddddiiiiooooffffiiiilllleeee....hhhh>>>>
-
- ////**** tttthhhhiiiissss rrrroooouuuuttttiiiinnnneeee aaaassssssssuuuummmmeeeessss ffffiiiilllleeee hhhhaaaannnnddddlllleeee iiiissss ooooppppeeeennnn,,,, aaaannnndddd bbbbuuuuffffffffeeeerrrr iiiissss aaaallllllllooooccccaaaatttteeeedddd ****////
- ////**** rrrreeeettttuuuurrrrnnnnssss nnnnuuuummmmbbbbeeeerrrr ooooffff ffffrrrraaaammmmeeeessss aaaaccccttttuuuuaaaallllllllyyyy rrrreeeeaaaadddd,,,, oooorrrr ----1111 oooonnnn eeeerrrrrrrroooorrrr ****////
-
- iiiinnnntttt rrrreeeeaaaaddddBBBBuuuuffffffffeeeerrrr((((AAAAFFFFffffiiiilllleeeehhhhaaaannnnddddlllleeee hhhh,,,, vvvvooooiiiidddd ****bbbbuuuuffffffffeeeerrrr,,,, iiiinnnntttt ffffrrrraaaammmmeeeessss))))
- {{{{
- iiiinnnntttt ffffrrrraaaammmmeeeessssRRRReeeeaaaadddd ==== aaaaffffRRRReeeeaaaaddddFFFFrrrraaaammmmeeeessss((((hhhh,,,, AAAAFFFF____DDDDEEEEFFFFAAAAUUUULLLLTTTT____TTTTRRRRAAAACCCCKKKK,,,, bbbbuuuuffffffffeeeerrrr,,,, ffffrrrraaaammmmeeeessss))));;;;
- iiiiffff((((ffffrrrraaaammmmeeeessssRRRReeeeaaaadddd <<<< 0000)))) {{{{ ////**** eeeerrrrrrrroooorrrr!!!! ****////
- ffffpppprrrriiiinnnnttttffff((((ssssttttddddeeeerrrrrrrr,,,, """"FFFFaaaattttaaaallll eeeerrrrrrrroooorrrr:::: %%%%ssss\\\\nnnn"""",,,, ddddmmmmGGGGeeeettttEEEErrrrrrrroooorrrr((((NNNNUUUULLLLLLLL,,,, NNNNUUUULLLLLLLL))))))));;;;
- rrrreeeettttuuuurrrrnnnn ----1111;;;;
- }}}}
- rrrreeeettttuuuurrrrnnnn ffffrrrraaaammmmeeeessssRRRReeeeaaaadddd;;;;
- }}}}
-
- Then elsewhere, prior to this call, you would have:
-
-
- aaaaffffSSSSeeeettttEEEErrrrrrrroooorrrrHHHHaaaannnnddddlllleeeerrrr((((NNNNUUUULLLLLLLL))));;;; ////**** ddddiiiissssaaaabbbblllleeee oooolllldddd----ssssttttyyyylllleeee gggglllloooobbbbaaaallll eeeerrrrrrrroooorrrr hhhhaaaannnnddddlllleeeerrrr ****////
-
- Now the most important caveat: users cannot make multiple,
- simultaneous, uncoordinated AF calls on the SAME
- AFfilehandle from different threads, even if the order of
- execution of those calls does not matter to the user. Doing
- so will very likely cause a core dump, or at least
- corruption of the AFfilehandle. This behavior will never be
- changed, as we refuse to make our developers pay the price
- of semaphore locking code at the beginning and end of every
- afReadFrames and afWriteFrames call. Most users do not
- need, and in fact really do not want, semaphore protection
-
-
-
-
-
-
-
-
-
-
-
- - 24 -
-
-
-
- that is built-in to the AF calls themselves.
-
- Like problem 2, problem 3 can occur with any AF call, not
- just afSeekFrame() and afReadFrames(). In particular, watch
- out for simultaneous calls of afSyncFile() and
- afCloseFile().
-
- Note that at no point did we offer any guarantee that the
- library was MT/MP-safe, and in fact only libraries specified
- as such in man pages (such as the C library minus errno, as
- explained in intro(3)) are guaranteed to be so.
-
- 9.7.7 _P_R_O_B_L_E_M__4 Some developers are using afOpenFD() or
- afGetFD() to get the file descriptor which an AFfilehandle
- is using, and then changing the file pointer on that file
- descriptor. The AF does not allow this.
-
- The file descriptor returned by afGetFD() was intended to be
- used as part of a select() loop and was not intended to
- allow users to read, write, and seek in the file without the
- knowledge of the Audio File Library. Doing so will cause
- the library to give unpredictable results unless the user
- saves and restores the file position whenever they modify
- it.
-
- The reason for this is that we are not willing to force upon
- users expecting high performance the often very large
- overhead of an lseek(2) system call on every afReadFrames()
- or afWriteFrames(). Therefore we cannot restore the file
- position to a known place on every AF call which relies on
- the file being in that place.
-
- Users who wish to modify the file position of the file
- descriptor given by afGetFD() should save the file position
- and restore it after they are finished and before they make
- the next AF call to read or write data to the file. The new
- routines _a_f_S_a_v_e_F_i_l_e_P_o_s_i_t_i_o_n(3dm) and
- _a_f_R_e_s_t_o_r_e_F_i_l_e_P_o_s_i_t_i_o_n(3dm) have been created expressly for
- this purpose. Alternately they can use one of two different
- file descriptors opened to the same file (dup(2) will not
- work; it gives you two file descriptors which share a file
- offset. The file must be re-opened in order to get a
- separate file descriptor). Also, if users attempt to write
- to the file, no matter how the AFfilehandle was opened, the
- results are undefined.
-
- Developers had asked for a call to get the offset of the
- audio data in an audio file. Two new functions have been
- made available. afGetDataOffset(3dm) returns the offset in
- bytes from the beginning of an open audio file to the first
- audio sample. afGetTrackBytes(3dm) returns the size in
-
-
-
-
-
-
-
-
-
-
-
- - 25 -
-
-
-
- bytes of the audio data portion of a given track in an audio
- file.
-
- 9.7.8 _W_A_R_N_I_N_G We give no guarantees about the number or
- nature of UNIX system calls that will result from a given AF
- call. In particular, afReadFrames() and afWriteFrames()
- could actually read() or write() any amount of data in the
- file, or could read() or write() more than once in varying
- chunk sizes. Also, afOpenFile(), afSeekFrame(),
- afSyncFile(), afCloseFile(), and other AF functions could
- result in any amount of data being read from or written to
- the file. (but of course the AF will not write to a file
- opened for read access or read from a file opened for write
- access).
-
- Users who are attempting to optimize the I/O in their
- program by managing I/O system call behavior should be aware
- that at this time we offer no guarantees about when the AF
- will perform system calls.
-
- This has not been a problem to our knowledge, but we thought
- it would be a good idea just to make this explicit. At this
- time we offer no guarantees that a read of, say, 50,000
- frames will result in a single UNIX read() system call for
- exactly 50,000 frames worth of data. Although we will
- strive to make this the case whenever it seems beneficial,
- there are certain cases where this is simply impossible.
- For example, reads from or writes to a compressed file will
- generally be split up into a chunksize which is natural for
- the codec being used, and thus possibly result in several
- reads or writes to the file. Also, we give no guarantee
- that afSeekFrame() will seek the file at all in the UNIX
- lseek() sense, although it happens that this is generally
- the case for the current Audio File Library. And even if
- afSeekFrame() does lseek() the file, we do not guarantee
- that it will be to the exact frame the user specified
- (though this is generally the case in the old AF library).
- This is due to necessary compensation for filter delays
- inherent in certain forms of compression and decompression.
-
- In a future release, features will be introduced which may
- make this more of an issue. At that time we will come up
- with much more specific information about what guarantees we
- can offer to the developer. We want to find out if these
- kinds of guarantees are something that developers need at
- all. Perhaps it is simply not an issue for developers. But
- if it is, we would be most interested in hearing your
- feedback. You can contact your local SGI representative and
- ask them to send a message to the developers of the Audio
- File Library, or you can also use the newsgroup
- comp.sys.sgi.audio for faster and much more direct contact.
-
-
-
-
-
-
-
-
-
-
-
- - 26 -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-